#ifndef PACKET_POOL_HH
#define PACKET_POOL_HH 1
#include "sncpacket.hh"
#include "simplehashtable.hh"
#include <click/hashtable.hh>
#include <click/dequeue.hh>

CLICK_DECLS

class PacketPool{
public:
	PacketPool(unsigned capacity):_cap(capacity),_pktpool(0),_queue(capacity){
		DPrintf("PacketPool constructed!");
	}
	NativePkt* get(uint32_t pkt_id){
		return _pktpool.get(pkt_id);
	}
	~PacketPool(){
		HashTable<uint32_t,NativePkt* >::iterator iter;
		for(iter=_pktpool.begin();iter!=_pktpool.end();++iter){
			delete iter.value();
		}
	}
	bool store(uint32_t pkt_id,NativePkt* native){
		if(_pktpool.size()<_cap){
			HashTable<uint32_t,NativePkt* >::iterator iter=_pktpool.find(pkt_id);
			if(iter!=_pktpool.end()){
				delete[] iter.value()->_data;
				delete iter.value();
				_pktpool.erase(iter);
			}
			_pktpool.set(pkt_id,native);
			_queue.push_back(pkt_id);
			_cap++;
		}
		else{
			uint32_t id=_queue.front();
			HashTable<uint32_t,NativePkt* >::iterator iter=_pktpool.find(id);
			if(iter!=_pktpool.end()){
				delete[] iter.value()->_data;
				delete iter.value();
				_pktpool.erase(iter);
			}
			_queue.pop_front();
			_queue.push_back(pkt_id);
			_pktpool.set(pkt_id,native);
		}
		return true;
	}
	void set_cap(unsigned cap){
		_cap=cap;
	}
protected:
	unsigned _cap;
	HashTable<uint32_t,NativePkt* > _pktpool;
	DEQueue<uint32_t > _queue;
};

class NeighborPacketPool{
public:
	NeighborPacketPool(unsigned capacity):_cap(capacity){
		DPrintf("NeighborPacketPool constructed!");
	}
	bool find(uint32_t pkt_id){
		return _pktpool.find(pkt_id);
	}
	bool store(uint32_t pkt_id){
		if(_pktpool.size()<_cap){
			_pktpool.insert(pkt_id);
			_queue.push_back(pkt_id);
			_cap++;
		}
		else{
			uint32_t id=_queue.front();
			_pktpool.erase(id);
			_queue.pop_front();
			_queue.push_back(pkt_id);
			_pktpool.insert(pkt_id);
		}
		return true;
	}
	void set_cap(unsigned cap){
		_cap=cap;
	}
protected:
	unsigned _cap;
	SNCoding::SimpleHashTable<uint32_t> _pktpool;
	DEQueue<uint32_t > _queue;
};

CLICK_ENDDECLS

#endif
